from PyQt5.QtCore import pyqtSignal, Qt
from PyQt5.QtWidgets import QWidget, QVBoxLayout, QGridLayout, QApplication
from sys import argv, exit
import matplotlib.pyplot as plt
from matplotlib.cm import ScalarMappable
from matplotlib.colors import Normalize
from mpl_toolkits.mplot3d import Axes3D
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from numpy import sin, cos, tan, pi, arctan, multiply, linspace, meshgrid

from Calculate_HighAzim2angle import Solar_angle

plt.rcParams['font.size'] = 10
plt.rcParams['font.family'] = 'Times New Roman'
plt.rcParams['axes.unicode_minus'] = False

class Button_Simulation(QWidget):

    Simulate_success_signal = pyqtSignal()

    def __init__(self, time_zone, lat, long, year, month, day, hours, minutes, seconds, Declination=None):
        super(Button_Simulation, self).__init__()
        self.setWindowTitle("AoP and DoP")
        self.setWindowModality(Qt.WindowModal)
        self.Declination_angle = Declination
        self.resize(600, 400)
        self.setStyleSheet('background-color: #ffffff;')
        self.time_zone = time_zone
        self.lat = lat
        self.long = long
        self.year = year
        self.month = month
        self.day = day
        self.hours = hours
        self.minutes = minutes
        self.seconds = seconds

        self.PsLine = None
        self.aop_xx = None

        self.VBoxLayout = QVBoxLayout()
        self.fig2 = plt.figure()
        self.canvas2 = FigureCanvas(self.fig2)

        self.fig3 = plt.figure()
        self.canvas3 = FigureCanvas(self.fig3)

        self.fig4, self.ax4 = plt.subplots()
        self.canvas4 = FigureCanvas(self.fig4)
        self.canvas4.setMinimumHeight(50)
        self.canvas4.setMaximumHeight(100)

        self.Right_LayoutZ = QVBoxLayout()
        self.Right_Layout = QGridLayout()

        self.Right_Layout.addWidget(self.canvas2, 0, 0)
        self.Right_Layout.addWidget(self.canvas3, 0, 1)
        self.Right_Layout.addWidget(self.canvas4, 1, 0, 1, 2)

        self.Right_LayoutZ.addLayout(self.Right_Layout)
        self.VBoxLayout.addLayout(self.Right_LayoutZ)
        self.setLayout(self.VBoxLayout)
        self.setup_signal()

    def setup_signal(self):
        Solar_Angle = Solar_angle(time_zone=self.time_zone, year=self.year, month=self.month, day=self.day,
                                hours=self.hours, minutes=self.minutes, seconds=self.seconds,
                                long=self.long, lat=self.lat,
                                Declination=self.Declination_angle)
        _, _, h_s, p_s = Solar_Angle.Calcu()
        t_s = 90 - h_s

        theta = linspace(0, 180, 160)
        theta = theta.round(4)
        phi = linspace(0, 360, 160)
        phi = phi.round(4)
        [T, P] = meshgrid(theta, phi)
        x = sin(T * pi / 180) * sin(P * pi / 180)
        y = sin(T * pi / 180) * cos(P * pi / 180)
        z = cos(T * pi / 180)

        k1 = cos(t_s * pi / 180) * sin(T * pi / 180) - sin(
            t_s * pi / 180) * cos(
            T * pi / 180) * cos((P - p_s) * pi / 180)
        k2 = sin(t_s * pi / 180) * sin((P - p_s) * pi / 180)

        k3 = sin(t_s * pi / 180) * sin(T * pi / 180) * cos(
            (p_s - P) * pi / 180) \
                  + cos(T * pi / 180) * cos(t_s * pi / 180)

        AoP = arctan((k1 / k2)) * 180 / pi
        DoP = (1 - multiply(k3, k3)) / (1 + multiply(k3, k3))

        PsAngle = 1 / tan(p_s * pi / 180)

        r = 1
        if 0 < p_s <= 90:
            k = p_s
            x_line = r * sin(k * pi / 180)
            self.aop_xx = linspace(-x_line, x_line, 10)
            self.PsLine = PsAngle * self.aop_xx
        elif 90 < p_s < 180:
            k = 180 - p_s
            x_line = r * sin(k * pi / 180)
            self.aop_xx = linspace(-x_line, x_line, 10)
            self.PsLine = PsAngle * self.aop_xx
        elif 180 < p_s < 270:
            k = 270 - p_s
            p_k = 90 - k
            x_line = r * sin(p_k * pi / 180)
            self.aop_xx = linspace(-x_line, x_line, 10)
            self.PsLine = PsAngle * self.aop_xx
        elif 270 < p_s < 360:
            k = 360 - p_s
            x_line = r * sin(k * pi / 180)
            self.aop_xx = linspace(-x_line, x_line, 10)
            self.PsLine = PsAngle * self.aop_xx
        elif p_s == 270:
            self.aop_xx = linspace(-1, 1, 10)
            self.PsLine = linspace(0, 0, 10)
        elif p_s == 0 or p_s == 180 or p_s == 360:
            self.aop_xx = linspace(0, 0, 10)
            self.PsLine = linspace(-1, 1, 10)

        ax2 = Axes3D(self.fig2, auto_add_to_figure=False)
        ax2.view_init(azim=-90, elev=90)
        self.fig2.add_axes(ax2)
        ax2.w_xaxis.set_pane_color((1.0, 1.0, 1.0, 1.0))
        ax2.w_yaxis.set_pane_color((1.0, 1.0, 1.0, 1.0))
        ax2.w_zaxis.set_pane_color((1.0, 1.0, 1.0, 1.0))

        # Get rid of the spines
        ax2.w_xaxis.line.set_color((1.0, 1.0, 1.0, 1.0))
        ax2.w_yaxis.line.set_color((1.0, 1.0, 1.0, 1.0))
        ax2.w_zaxis.line.set_color((1.0, 1.0, 1.0, 1.0))

        ax2.set_xlabel("X:W-E")
        ax2.set_ylabel("Y:S-N")
        ax2.set_zlabel("Z")

        scalarMap02 = ScalarMappable(norm=Normalize(vmin=AoP.min(), vmax=AoP.max()), cmap=plt.get_cmap('jet'))
        C_colored = scalarMap02.to_rgba(-AoP)
        ax2.plot_surface(x, y, z, facecolors=C_colored, rstride=1, cstride=1, shade=False, zorder=2)
        ax2.plot(self.aop_xx, self.PsLine, '-k', zorder=3)
        ax2.grid(False)
        ax2.axis('off')
        self.canvas2.draw()

        ax3 = Axes3D(self.fig3, auto_add_to_figure=False)
        ax3.view_init(azim=-90, elev=90)
        self.fig3.add_axes(ax3)
        ax3.w_xaxis.set_pane_color((1.0, 1.0, 1.0, 1.0))
        ax3.w_yaxis.set_pane_color((1.0, 1.0, 1.0, 1.0))
        ax3.w_zaxis.set_pane_color((1.0, 1.0, 1.0, 1.0))

        ax3.w_xaxis.line.set_color((1.0, 1.0, 1.0, 1.0))
        ax3.w_yaxis.line.set_color((1.0, 1.0, 1.0, 1.0))
        ax3.w_zaxis.line.set_color((1.0, 1.0, 1.0, 1.0))
        ax3.set_xlabel("X:W-E")
        ax3.set_ylabel("Y:S-N")
        ax3.set_zlabel("Z")
        scalarMap13 = ScalarMappable(norm=Normalize(vmin=DoP.min(), vmax=DoP.max()), cmap=plt.get_cmap('jet'))
        D_colored = scalarMap13.to_rgba(DoP)
        ax3.plot_surface(x, y, z, facecolors=D_colored, rstride=1, cstride=1, shade=False, zorder=2)
        ax3.plot(self.aop_xx, self.PsLine, '-k', zorder=3)
        ax3.grid(False)
        ax3.axis("off")
        self.canvas3.draw()

        self.fig4.subplots_adjust(bottom=0.6)
        norm = Normalize(vmin=AoP.min(), vmax=AoP.max())

        self.fig4.colorbar(
            ScalarMappable(norm=norm, cmap=plt.get_cmap('jet')),
            cax=self.ax4,
            orientation="horizontal",)
        self.canvas4.draw()


if __name__ == '__main__':
    app = QApplication(argv)
    MainWindow = Button_Simulation(8, 36.002243, 120.129118, 2022, 10, 19, 15, 22, 2)
    MainWindow.show()
    exit(app.exec_())

